package com.example.lp.lpuicore.views.view.move;

import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import static com.example.lp.lpuicore.views.view.move.MoveView.MODE.*;


/**
 * Author by lp,on 2021/3/5/005,11:21.
 */
public class MoveView extends View {
    private static final String TAG = "MoveView";
    private int lastX;
    private int lastY;
    private Scroller scroller;

    @MODE
    private int mode = MODE_LAYOUT;

    public MoveView(Context context) {
        super(context);
        Log.i(TAG, "MoveView:1 ");
    }

    public MoveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
        Log.i(TAG, "MoveView:2 ");
    }

    public MoveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        Log.i(TAG, "MoveView: 3");
    }

    private void init() {
//        setOnTouchListener(this);
        scroller = new Scroller(getContext());
    }

    public void switchMode(@MODE int mode) {
        this.mode = mode;
    }

    @Retention(RetentionPolicy.SOURCE)
    //2.定义int 值 ，
    //写法1： flag true表示可以用 MODE_STANDARD|MODE_LIST 或者 MODE_LIST & MODE_TABS 这种方式使用，然并卵 ,默认false
    @IntDef(flag = true, value = {MODE_LAYOUT, MODE_OFFSET, MODE_LAYOUTPARAMS, MODE_SCROLL, MODE_ANIMATION, MODE_SCROLLER, MODE_TABS})
    //写法2：
    //@IntDef({MODE_STANDARD, MODE_LIST, MODE_TABS})
    //3.定义注解类型
    public @interface MODE {
        int MODE_LAYOUT = 1;      //默认是 public static final
        int MODE_OFFSET = 2;
        int MODE_LAYOUTPARAMS = 3;
        int MODE_SCROLL = 4;
        int MODE_ANIMATION = 5;
        int MODE_SCROLLER = 6;
        int MODE_TABS = 7;
    }


    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent: ");
        //获取到手指处的横坐标和纵坐标
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                move(event, lastX, lastY, x, y);
                break;
        }

        return true;
    }

    private void move(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        switch (mode) {
            case MODE_LAYOUT:
                layoutMove(event, lastX, lastY, nowX, nowY);
                break;
            case MODE_OFFSET:
                offsetMove(event, lastX, lastY, nowX, nowY);
                break;
            case MODE_LAYOUTPARAMS:
                layoutParmsMove(event, lastX, lastY, nowX, nowY);
                break;
            case MODE_SCROLL:
                scrollMove(event, lastX, lastY, nowX, nowY);
                break;
            case MODE_ANIMATION:
                animMove(event, lastX, lastY, nowX, nowY);
                break;
            case MODE_SCROLLER:
                scrollerMove(event, lastX, lastY, nowX, nowY);
                break;
        }

    }

    private void layoutMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        Log.i(TAG, "layoutMove: ");
        //计算移动的距离
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        //调用layout方法来重新放置它的位置
        layout(getLeft() + offX, getTop() + offY,
                getRight() + offX, getBottom() + offY);
    }

    private void offsetMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        Log.i(TAG, "offsetMove: ");
        //计算移动的距离
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        offsetLeftAndRight(offX);
        offsetTopAndBottom(offY);
    }

    private void layoutParmsMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        Log.i(TAG, "layoutParmsMove: ");
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        //获取外边距的参数信息
        ViewGroup.MarginLayoutParams mLp = (ViewGroup.MarginLayoutParams) getLayoutParams();
        //设置边距参数
        mLp.leftMargin = getLeft() + offX;
        mLp.topMargin = getRight() + offY;
        setLayoutParams(mLp);

    }

    private void scrollMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        Log.i(TAG, "scrollMove: ");
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        Log.i(TAG, "nowX: " + nowX);
        Log.i(TAG, "nowY: " + nowY);
        Log.i(TAG, "offX: " + offX);
        Log.i(TAG, "offY: " + offY);
        ((View) getParent()).scrollBy(-offX, -offY);
    }


    private void animMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        Log.i(TAG, "animMove: ");

//        ObjectAnimator.ofFloat(this, "translationX", 0, 100).setDuration(1000).start();

        View parent = (View) getParent();
        ValueAnimator animator=ValueAnimator.ofFloat(0,1).setDuration(1000);
        animator.addUpdateListener(animation -> {
            float fraction=animation.getAnimatedFraction();
            parent.scrollTo((int) (-200*fraction),0);

        });
        animator.start();
    }

    private void scrollerMove(MotionEvent event, int lastX, int lastY, int nowX, int nowY) {
        Log.i(TAG, "scrollerMove: ");
        int offX = nowX - lastX;
        int offY = nowY - lastY;
        View parent = (View) getParent();
        scroller.startScroll(parent.getScrollX(), parent.getScrollY(), -offX, -offY);
    }

    //不断改变 mScrollX，mScrollY的位置，重绘实现弹性滑动效果
    public void computeScroll() {
        super.computeScroll();
        if (scroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo(scroller.getCurrX(),
                    scroller.getCurrY());
        }
        invalidate();//必须要调用
    }
}